// #pragma once

// #ifndef __ThreadPool_hpp__
// #define __ThreadPool_hpp__

#include <iostream>
#include <pthread.h>
#include <vector>
#include <queue>
#include <string>

static const int defaultnum = 5;

struct ThreadInfo
{
    pthread_t tids;
    std::string NameThread;
};

template<class T>
class ThreadPool
{
public:
    void Lock()
    {
        pthread_mutex_lock(&lock);
    }

    void UnLock()
    {
        pthread_mutex_unlock(&lock);
    }

    void Wait()
    {
        pthread_cond_wait(&cond, &lock);
    }

    void WakeUp()
    {
        pthread_cond_signal(&cond);
    }

    bool IsEmptyTask()
    {
        return _TasksQueue.size() == 0;
    }

public:
    ThreadPool(int num = defaultnum): _threads(num)
    {
        pthread_mutex_init(&lock, nullptr);
        pthread_cond_init(&cond, nullptr);
    }

    void ThreadStart()
    {
        int n = _threads.size();
        for(int i = 0; i < n; i++)
        {
            pthread_create(&_threads[i].tids, nullptr, ThreadTasks, this);
            _threads[i].NameThread = "thread-" + std::to_string(i);
        }
    }

    std::string GetThreadName(pthread_t tid)
    {
        for(auto& e : _threads)
        {
            if(tid == e.tids)
            {
                return e.NameThread; 
            }
        }

        return "none";
    }

    static void *ThreadTasks(void* args)
    {
        ThreadPool<T>* TP = static_cast<ThreadPool<T>*>(args);

        while(true)
        {
            std::string Name = TP->GetThreadName(pthread_self());

            TP->Lock();
            while(TP->IsEmptyTask()) //防止伪唤醒
            {
                TP->Wait();
            }

            T t = TP->pop();

            TP->UnLock();

            t();

            std::cout << Name.c_str() << ' ' << std::endl;
	    t.GetTask();
        }
    }

    T pop()
    {
        T t = _TasksQueue.front();
        _TasksQueue.pop();

        return t;
    }

    void push(const T &task)
    {
        Lock();
        _TasksQueue.push(task);
        WakeUp();
        UnLock();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }
private:
    std::vector<ThreadInfo> _threads;
    std::queue<T> _TasksQueue;

    pthread_mutex_t lock;
    pthread_cond_t cond;
};

// static int defaultnum = 10;

// struct ThreadData
// {
//     pthread_t tid;
//     std::string threadname = "thread->";
// };

// template<class T>
// class ThreadPool
// {
//     bool isEmpty()
//     {
//         return _BlockQueue.size() == 0;
//     }
//     bool isFull()
//     {
//         return _BlockQueue.size() == _num;
//     }
//     void Lock()
//     {   
//         pthread_mutex_lock(&lock);
//     }
//     void UnLock()
//     {
//         pthread_mutex_unlock(&lock);
//     }
//     void Wait()
//     {
//         pthread_cond_wait(&cond, &lock);
//     }
//     void WakeUp()
//     {
//         pthread_cond_signal(&cond);
//     }
// public:
//     ThreadPool(int num = defaultnum): _num(num)
//     {
//         pthread_mutex_init(&lock, nullptr);
//         pthread_cond_init(&cond, nullptr);

//         // ThreadInit();
//     }

//     void ThreadStart()
//     {
//         std::vector<ThreadData*> tds;
//         std::vector<pthread_t> tids;
//         for(int i = 0; i < _num; i++)
//         {
//             ThreadData *td = new ThreadData;
//             tds.push_back(td);
//             pthread_create(&(td->tid), nullptr, ThreadRoutine, this);
//             tids.push_back(td->tid);
//         }

//         for(int i = 0; i < tds.size(); i++)
//         {
//             delete tds[i];
//         }

//         //mian函数中执行流(主线程)调用构造函数之后一直在等待其他线程，导致不能执行main函数中后续代码，会一直卡在这个地方
//         //最好使用线程分离或者不使用join进行等待
//         // for(int i = 0; i < _num; i++)
//         // {
//         //     pthread_join(tids[i], nullptr);
//         // }
//     }

//     static void *ThreadRoutine(void *args)
//     {
//         pthread_detach(pthread_self());
//         ThreadPool<T> *td = static_cast<ThreadPool<T>*>(args);
//         while(true)
//         {
//             td->Lock();
//             while(!td->isEmpty()) //防止使用pthread_cond_broadcast造成的伪唤醒
//             {
//                 td->Wait();    
//             }

//             T t = td->pop();
//             td->UnLock();
//             t();
//             printf("pthread ThreadRoutine\n");
//         }

//         pthread_exit((void*)666);
//     }

//     void push(T &task)
//     {
//         Lock();
//         _BlockQueue.push(task);
//         WakeUp();
//         UnLock();
//     }

//     T pop() //在threadroutine中已经进行了保护
//     {
//         T task = _BlockQueue.front();
//         _BlockQueue.pop();
//         return task;
//     }

//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&lock);
//         pthread_cond_destroy(&cond);
//     }
// private:
//     std::queue<T> _BlockQueue; //阻塞队列
//     int _num;

//     pthread_mutex_t lock;
//     pthread_cond_t cond;
// };

// #endif
